﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace AnOtherBlog.Core
{
	public class Post : BlogBaseClass<Post, Guid>
	{

		#region Constructor

		/// <summary>
		/// Constructor por defecto
		/// </summary>
		public Post()
		{
			base.Id = Guid.NewGuid();
			base.DateCreated = DateTime.Now;

			_IsPublished = true;
			_IsCommentEnabled = true;

			_Categories = new List<Category>();
			_Tags = new List<string>();
			_Comments = new List<Comment>();
			_NotificationEmails = new List<string>();
		}

		#endregion

		#region Fields and Properties

		/// <summary>
		/// Identificador único de la publicación
		/// Id de la clase base
		/// </summary>
		public Guid PostID
		{
			get
			{
				return this.Id;
			}
			set
			{
				this.Id = value;
			}
		}

		private string _Title;
		/// <summary>
		/// Título de la publicación
		/// </summary>
		public string Title
		{
			get
			{
				return _Title;
			}
			set
			{
				_Title = value ?? string.Empty;
			}
		}

		private string _Description;
		/// <summary>
		/// Descripción (SEO)
		/// </summary>
		public string Description
		{
			get
			{
				return _Description;
			}
			set
			{
				_Description = value ?? string.Empty;
			}
		}

		private string _PostContent;
		/// <summary>
		/// Contenido de la publicación
		/// </summary>
		public string PostContent
		{
			get
			{
				return _PostContent;
			}
			set
			{
				_PostContent = value ?? string.Empty;
			}
		}

		private string _Author;
		/// <summary>
		/// Autor de la publicación.
		/// </summary>
		public string Author
		{
			get { return _Author; }
			set
			{
				_Author = value ?? string.Empty;
			}
		}

		private bool _IsPublished;
		/// <summary>
		/// Está publicado
		/// </summary>
		public bool IsPublished
		{
			get
			{
				return _IsPublished;
			}
			set
			{
				_IsPublished = value;
			}
		}

		private bool _IsCommentEnabled;
		/// <summary>
		/// Habilita comentarios
		/// </summary>
		public bool IsCommentEnabled
		{
			get
			{
				return _IsCommentEnabled;
			}
			set
			{
				_IsCommentEnabled = value;
			}
		}

		private string _Slug;
		/// <summary>
		/// El Slug de una publicación es un URL utilizado para acceder al mismo.
		/// </summary>
		public string Slug
		{
			get
			{
				if (string.IsNullOrEmpty(_Slug))
					return Util.RemoveIllegalCharacters(Title);
				return _Slug;
			}
			set
			{
				_Slug = value ?? string.Empty;
			}
		}

		/// <summary>
		/// El URL absoluto de la publicación
		/// </summary>
		[XmlIgnore()]
		public Uri LinkAbsolute
		{
			get
			{
				return Util.ConvertToAbsolute(this.LinkRelative);
			}
		}

		/// <summary>
		/// El path (relativo) de la publicación
		/// </summary>
		[XmlIgnore()]
		public string LinkRelative
		{
			get
			{
				return Util.WebRootRelative + "post/" + this.Slug + ".aspx";
			}
		}


		private List<Category> _Categories;
		/// <summary>
		/// Coleccion de categorías asociadas a la publicación
		/// </summary>
		public List<Category> Categories
		{
			get
			{
				if (_Categories == null)
				{
					_Categories = new List<Category>();
				}
				return _Categories;
			}
		}

		private List<string> _Tags;
		/// <summary>
		/// Colección de margas (tags) asociadas a la publicación
		/// </summary>
		public List<string> Tags
		{
			get
			{
				if (_Tags == null)
				{
					_Tags = new List<string>();
				}
				return _Tags;
			}
		}

		private List<Comment> _Comments;
		/// <summary>
		/// Colección de comentarios asociados al post
		/// </summary>
		public List<Comment> Comments
		{
			get
			{
				if (_Comments == null)
				{
					_Comments = new List<Comment>();
				}
				return _Comments;
			}
		}

		/// <summary>
		///	Colección de comentarios Aprobados
		/// </summary>
		public List<Comment> CommentsApproved
		{
			get
			{
				return _Comments.FindAll(
						delegate(Comment obj)
						{
							return obj.IsApproved;
						}
					);
			}
		}

		/// <summary>
		///	Colección de comentarios NO Aprobados
		/// </summary>
		public List<Comment> CommentsNotApproved
		{
			get
			{
				return _Comments.FindAll(
						delegate(Comment obj)
						{
							return !obj.IsApproved;
						}
					);
			}
		}

		private List<string>  _NotificationEmails;
		/// <summary>
		/// Colección de cuentas de email que reciben notificaciones
		/// </summary>
		public List<string> NotificationEmails
		{
			get
			{
				if (_NotificationEmails == null)
				{
					_NotificationEmails = new List<string>();
				}
				return _NotificationEmails;
			}
		}

		private int _BlogID;
		/// <summary>
		/// Identificador único del blog (en esta base de datos)
		/// </summary>
		public int BlogID
		{
			get
			{
				return _BlogID;
			}
			set
			{
				_BlogID = value;
			}
		}

		/// <summary>
		/// Constantes para manipular la forma en que se ordenan
		/// las publicaciones al traerlas de la base de datos
		/// Ahora las estamos ordenando en la colección, sería 
		/// mejor si utilizamos ORDER BY en el SQL query
		/// </summary>
		public enum PostSort
		{
			ID = 0,
			Title = 1,
			DateCreated = 2,
			DateModified = 3,
		}


		#endregion

		#region Persist Methods

		/// <summary>
		/// Obtiene una publicación de acuerdo a su id.
		/// </summary>
		/// <param name="id">Identificador de la publicación </param>
		/// <returns>Objeto publicación</returns>
		public static Post Load(Guid id)
		{
			return Providers.DataAccess.PostSelect(id);
		}

		/// <summary>
		/// Obtiene una colección con todas las publiaciones
		/// CUIDADO se come toda la memoria !!!!!!!!!!!!!!!!!!!!!!!!
		/// </summary>
		/// <returns>Colección con todas las publicaciones del blog</returns>
		public static List<Post> LoadAll()
		{
			return Providers.DataAccess.PostList();
		}
		/// <summary>
		/// Obtiene una colección con todas las publiaciones
		/// </summary>
		/// <param name="isProxy">Indica el modo de lectura (true = lectura reducida)</param>
		/// <returns>Colección con todas las publicaciones del blog</returns>
		public static List<Post> LoadAll(bool isProxy)
		{
			return Providers.DataAccess.PostList(isProxy);
		}

		/// <summary>
		/// Obtiene una colección con todas las publiaciones
		/// </summary>
		/// <param name="sort">Indica el modo de ordenación</param>
		/// <returns>Colección con todas las publicaciones del blog</returns>
		/// <remarks>
		/// Asume modo de lectura completo
		/// </remarks>
		public static List<Post> LoadAll(PostSort sort)
		{
			return LoadAll(sort, false);
		}

		/// <summary>
		/// Obtiene una colección con todas las publiaciones
		/// </summary>
		/// <param name="sort">Indica el modo de ordenación</param>
		/// <param name="isProxy">Indica el modo de lectura (true = lectura reducida)</param>
		/// <returns>Colección con todas las publicaciones del blog</returns>
		public static List<Post> LoadAll(PostSort sort, bool isProxy)
		{
			List<Post> posts = LoadAll(isProxy);
			switch (sort)
			{
				case PostSort.ID:
					break;

				case PostSort.Title:
					posts.Sort(delegate(Post p1, Post p2)
					{
						return String.Compare(p1.Title, p2.Title);
					});
					break;

				case PostSort.DateCreated:	// mayor a menor
					posts.Sort(delegate(Post p1, Post p2)
					{
						return DateTime.Compare(p2.DateCreated, p1.DateCreated);
					});
					break;

				case PostSort.DateModified:	// mayor a menor
					posts.Sort(delegate(Post p1, Post p2)
					{
						return DateTime.Compare(p2.DateModified, p1.DateModified);
					});
					break;

			}
			return posts;
		}
		/// <summary>
		/// Almacena la publicación
		/// </summary>
		public void Save()
		{
			this.DateModified = DateTime.Now;
			if (this.IsNew)
			{
				Providers.DataAccess.PostInsert(this);
				// TODO: Revisar si es en este punto donde agrego a la lista 
				Blog.Current.ReLoadPosts();
			}
			else
			{
				Providers.DataAccess.PostUpdate(this);
			}
		}

		#endregion

	}
}
